package com.miya.demo.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.miya.demo.common.util.MinioUtil;
import com.miya.demo.common.util.QrCodeUtil;
import com.miya.demo.common.util.RedisUtil;
import com.miya.demo.entity.Customer;
import com.miya.demo.model.base.BaseResponse;
import com.miya.demo.model.dto.CustomerAddDTO;
import com.miya.demo.model.vo.DataMaskDemoVO;
import com.miya.demo.service.CustomerService;
import com.miya.demo.service.PushMsgService;
import com.miya.demo.support.kafka.producer.KafkaSendHandler;
import com.miya.demo.support.netty.bean.DataContent;
import com.miya.demo.support.rabbitmq.delay.DelayDemoConfig;
import com.miya.demo.support.rabbitmq.dto.DelayDemoLetterDTO;
import com.miya.demo.support.websocket.WebSocketServer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 测试控制器
 *
 * @author Caixiaowei
 * @date 2021/09/22
 */
@RestController
@RequestMapping("/test")
@Api(tags = "测试 API")
@Slf4j
public class TestController {

	@Autowired
	private CustomerService customerService;
	@Autowired
	private MinioUtil minioUtil;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private RabbitTemplate rabbitTemplate;

	/********************* mybatis-plus 测试 **********************/

	@ApiOperation(value = "保存客户", notes = "Corki")
	@GetMapping("/list")
	public BaseResponse<List<Customer>> list(String name) {
		return BaseResponse.create(customerService.list());
	}

	@ApiOperation(value = "保存客户", notes = "Corki")
	@PostMapping("/saveCustomer")
	public BaseResponse<Object> saveCustomer(@RequestBody @Validated CustomerAddDTO dto) {
		Customer customer = new Customer();
		BeanUtil.copyProperties(dto, customer, CopyOptions.create().ignoreNullValue());
		return BaseResponse.create(customerService.save(customer));
	}

	/********************* minio 测试 **********************/

	@ApiOperation(value = "创建bucket", notes = "Corki")
	@GetMapping("/makeBucket")
	public BaseResponse<Boolean> makeBucket(String bucketName) throws Exception {
		boolean b = minioUtil.makeBucket(bucketName, null);
		return BaseResponse.create(b);
	}

	@ApiOperation(value = "验证bucket 是否存在", notes = "Corki")
	@GetMapping("/bucketExists")
	public BaseResponse<Boolean> bucketExists(String bucketName) throws Exception {
		boolean b = minioUtil.bucketExistes(bucketName);
		return BaseResponse.create(b);
	}

	@PostMapping("/putObject")
	public BaseResponse<String> putObject(@RequestParam("file") MultipartFile file) throws IOException {
		String objectUrl = minioUtil.putObject(MinioUtil.DEFAULT_BUCKET, file.getOriginalFilename(), file.getInputStream());
		return BaseResponse.create(objectUrl);
	}

	/********************* easyexcel 测试 **********************/

	@ApiOperation(value = "上传Excel", notes = "Corki")
	@PostMapping("/uploadExcel")
	public BaseResponse<Void> uploadExcel(@RequestParam("file") MultipartFile file) throws IOException {
		customerService.uploadExcel(file);
		return BaseResponse.create();
	}

	@ApiOperation(value = "下载Excel", notes = "Corki")
	@GetMapping("/downloadExcel")
	public void downloadExcel() {
		customerService.downloadExcel();
	}

	@ApiOperation(value = "下载Excel2", notes = "Corki")
	@GetMapping("/downloadExcel2")
	public void downloadExcel2(HttpServletResponse response) {
		customerService.downloadExcel2(response);
	}

	@ApiOperation(value = "excel模板导出下载", notes = "Corki")
	@GetMapping("/downloadExcelOfTemplate")
	public void downloadExcelOfTemplate(HttpServletResponse response) {
		customerService.downloadExcelOfTemplate(response);
	}

	@ApiOperation(value = "excel异步导出zip", notes = "Corki")
	@GetMapping("/downloadAsync")
	public BaseResponse downloadAsync() {
		return BaseResponse.create(customerService.exportBigData3());
	}



	/********************* rabbitmq 测试 **********************/

	@GetMapping("/sendProductSalesChange")
	public BaseResponse<Void> sendProductSalesChange() {

		JSONObject jsonObject = new JSONObject();
		jsonObject.set("id", "1");
		jsonObject.set("name", "蔡晓威");

		rabbitTemplate.convertAndSend("stockMarketExchange", null, JSONUtil.toJsonStr(jsonObject));
		return BaseResponse.create();
	}

	@GetMapping("/sendTopicMsg")
	public BaseResponse<Void> sendTopicMsg() {
		for (int i = 0; i < 5; i++) {
			rabbitTemplate.convertAndSend("simpleExchange", "simple.message", "hello topic rabbitmq" + i);
		}
		return BaseResponse.create();
	}

	@ApiOperation(value = "发送延时demo消息")
	@GetMapping("/sendDelayDemo")
	public BaseResponse<Void> sendDelayDemo() {
		DelayDemoLetterDTO letterDTO = DelayDemoLetterDTO.builder()
				.messageId(IdUtil.fastSimpleUUID())
				.build();
		rabbitTemplate.convertAndSend(DelayDemoConfig.DELAY_EXCHANGE,
				DelayDemoConfig.DELAY_ROUTINGKEY, JSONUtil.toJsonStr(letterDTO),
				message -> {
					message.getMessageProperties().setDelay(10000);
					return message;
				});
		log.info("延迟demo发送: {}, 发送时间: {}", JSONUtil.toJsonStr(letterDTO),
				DateUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN));
		return BaseResponse.create();
	}

	/********************* redis 测试 **********************/

	@ApiOperation(value = "测试redis", notes = "Corki")
	@GetMapping("/testRedis")
	public BaseResponse<String> testRedis(String key, String value) throws IOException {
		redisUtil.set(key, value);
		return BaseResponse.create();
	}

	/********************* satoken 测试 **********************/

	@ApiOperation("测试鉴权-角色")
	@GetMapping("/testRole")
	@SaCheckRole("admin")
	public BaseResponse<Void> testRole() {
		return BaseResponse.create();
	}

	@ApiOperation("测试鉴权-资源权限")
	@GetMapping("/testPermisson")
	@SaCheckPermission("test:add")
	public BaseResponse<Void> testPermisson() {
		return BaseResponse.create();
	}

	@ApiOperation("测试鉴权-设定校验模式")
	@GetMapping("/testCheckMode")
	@SaCheckPermission(value = {"test:add", "test:del"}, mode = SaMode.OR)
	public BaseResponse<Void> testCheckMode() {
		return BaseResponse.create();
	}

	@ApiOperation("测试鉴权-角色权限双模式")
	@GetMapping("/testDualMode")
	@SaCheckPermission(value = "test:add", orRole = "admin")
	public BaseResponse<Void> testDualMode() {
		return BaseResponse.create();
	}


	/********************* zxing 二维码测试 **********************/

	@Autowired
	private QrCodeUtil qrCodeUtil;

	@ApiOperation("zxing-生成二维码")
	@GetMapping("/createQrcode")
	public BaseResponse<String> createQrcode(String content, String logoPath) throws Exception {
		return BaseResponse.create(qrCodeUtil.save(content, logoPath));
	}

	/*************** 测试url: url包含有空格，无法正常请求，需要对url进行格式化编码*******************************/

	@PostMapping("/testUrl")
	public BaseResponse<Void> testUrl(HttpServletResponse response) throws Exception {
		String url = "https://ignite-upload.oss-cn-shanghai.aliyuncs.com/prod/5c3fe5e0-0c17-48fb-b5fc-194406e47df4-1 (2).png";
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 创建uri
		URIBuilder builder = new URIBuilder(url);
		URI uri = builder.build();
		// 创建http GET请求
		HttpGet httpGet = new HttpGet(uri);
		// 执行请求
		CloseableHttpResponse httpResponse = httpclient.execute(httpGet);
		InputStream inputStream = httpResponse.getEntity().getContent();
		IoUtil.copy(inputStream, response.getOutputStream());
		return BaseResponse.create();
	}

	/**
	 * 测试url: url包含有空格，无法正常请求，需要对url进行格式化编码
	 *
	 * @param response 响应
	 * @return {@link BaseResponse}<{@link Void}>
	 * @throws Exception 异常
	 */
	@PostMapping("/testUrl2")
	public BaseResponse<Void> testUrl2(HttpServletResponse response) throws Exception {
		String url = "https://ignite-upload.oss-cn-shanghai.aliyuncs.com/prod/5c3fe5e0-0c17-48fb-b5fc-194406e47df4-1 (2).png";
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 创建uri
		URIBuilder builder = new URIBuilder(URLUtil.toUrlForHttp(url).toURI());
		URI uri = builder.build();
		// 创建http GET请求
		HttpGet httpGet = new HttpGet(uri);
		// 执行请求
		CloseableHttpResponse httpResponse = httpclient.execute(httpGet);
		InputStream inputStream = httpResponse.getEntity().getContent();
		IoUtil.copy(inputStream, response.getOutputStream());
		return BaseResponse.create();
	}


	/****************************** hutool 验证码 *******************************/

	@GetMapping("/captcha")
	public void captcha(String key, HttpServletResponse response) throws IOException {
		LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 80);
		lineCaptcha.createCode();
		String code = lineCaptcha.getCode();
		lineCaptcha.write(response.getOutputStream());
		redisUtil.set("captcha:" + key, code, 10, TimeUnit.MINUTES);
	}

	@GetMapping("/captcha/verify")
	public void captcha(String key, String captcha) throws IOException {
		LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 80);
		boolean verify = lineCaptcha.verify(captcha);
		System.out.println(verify);
		String newCaptcha = redisUtil.get("captcha:" + key).toString();
		boolean equals = StrUtil.equals(captcha, newCaptcha);
		System.out.println(equals);
	}

	/****************************** websocket 测试 *******************************/

	@Autowired
	private WebSocketServer webSocketServer;
	@GetMapping("/websocketSend")
	public void websocketSend(String userId, String message) {
		webSocketServer.sendOneMessage(StrUtil.isNotEmpty(userId) ? userId: "10086", StrUtil.isNotEmpty(message) ? message : "test001");
	}

	/****************************** netty 测试 *******************************/

	@Autowired
	private PushMsgService pushMsgService;

	@PostMapping("/pushOne")
	public void pushOne(@RequestBody DataContent dataContent){
		pushMsgService.pushMsgToOne(dataContent);
	}
	@PostMapping("/pushAll")
	public void pushAll(@RequestBody DataContent dataContent){
		pushMsgService.pushMsgToAll(dataContent);
	}

	/****************************** kafka 测试 *******************************/

	@Autowired
	private KafkaSendHandler kafkaSendHandler;

	@GetMapping("/kafkaSendOne")
	public void kafkaSendOne() {
		kafkaSendHandler.sendProducerRecord("kafkaSendOne hello kafka");
	}

	@GetMapping("/kafkaSendBatch")
	public void kafkaSendBatch() {
		for (int i = 0; i < 20; i++) {
			kafkaSendHandler.sendProducerRecord("kafkaSendBatch hello kafka " + i);
		}
	}

	@GetMapping("/getDataMaskDemoVOs")
	public BaseResponse<List<DataMaskDemoVO>> getDataMaskDemoVOs() {
		ArrayList<DataMaskDemoVO> list = CollUtil.newArrayList(
				new DataMaskDemoVO("corki", "13530660330", "上海市浦东新区和平路355号"),
				new DataMaskDemoVO("miya", "18310495243", "上海市浦东新区和平路355号"),
				new DataMaskDemoVO("蔡晓威-刘美辰静", "135000000", "上海市浦东新区和平路355号")
		);
		return BaseResponse.create(list);
	}
}
